from django.core.paginator import Paginator
from django.utils.dateparse import parse_datetime
from rest_framework import status, permissions
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.permissions import BasePermission
from rest_framework.response import Response
from rest_framework.views import APIView
import ReportManager.models
import ReportManager.serializers
from ReportManager.models import *  # 或者显式导入每个模型类
from UserManager.models import User

model_dict = ReportManager.models.model_dict
serializer_dict = ReportManager.serializers.serializer_dict


# 获取所有模型的字段与属性，用字典储存
# 获取模型字段信息
def get_model_fields_info(model_class):
    fields_info = {'model_name': model_class._meta.verbose_name}

    for field in model_class._meta.get_fields(include_hidden=True):
        # 获取字段的基本信息
        field_name = field.name
        field_type = field.__class__.__name__
        verbose_name = field.verbose_name

        # 获取choices信息，如果有的话
        choices = None
        if hasattr(field, 'choices') and field.choices:
            choices = field.choices
            # 提取每个子数组的第一个元素
            choices = [sublist[0] for sublist in choices]

        # 将信息存入字典
        fields_info[field_name] = {
            'type': field_type,
            'verbose_name': verbose_name,
            'choices': choices,
        }
    # 让模型以下字段排在前面
    """"id" "authors""time""attachment""reviewer""revstatus""review_time""max_score""score_weights""score
    ""created_time""modified_time""remark"""
    fields_info_public = {
        'authors': fields_info.pop('authors'),
        'time': fields_info.pop('time'),
        'attachment': fields_info.pop('attachment'),
        'reviewer': fields_info.pop('reviewer'),
        'revstatus': fields_info.pop('revstatus'),
        'review_time': fields_info.pop('review_time'),
        'max_score': fields_info.pop('max_score'),
        'score_weights': fields_info.pop('score_weights'),
        'score': fields_info.pop('score'),
        'created_time': fields_info.pop('created_time'),
        'modified_time': fields_info.pop('modified_time'),
        'remark': fields_info.pop('remark'),
        #'input_info': model_class.input_info
    }
    fields_info.update(fields_info_public)

    return fields_info


# 获取所有模型类
report_manager_config = apps.get_app_config('ReportManager')
model_classes = report_manager_config.get_models()
# 构建模型信息字典

model_info_dict = {model.__name__: get_model_fields_info(model) for model in model_classes}

# 权限管理
"""
reviewer:可以审核所有report
TDAdmin:可以审核所有report，并且可以添加和删除report
"""


class IsReviewer(BasePermission):

    def has_permission(self, request, view):
        # 假设您有一个名为 'reviewer' 的用户组

        return request.user.groups.filter(name='reviewer').exists()


class IsTDAdmin(BasePermission):
    def has_permission(self, request, view):
        # 假设您有一个名为 'TDAdmin' 的用户组

        return request.user.groups.filter(name='TDAdmin').exists()


class IsTDAdminOrIsReviewer(BasePermission):
    def has_permission(self, request, view):
        # 检查用户是否是管理员或审核者
        return request.user.groups.filter(name='TDAdmin').exists() or request.user.groups.filter(
            name='reviewer').exists()


# 创建
class CreateView(APIView):
    # 定义一个Report字段为空对象
    Report = None
    Serializer = None
    permission_classes = [IsTDAdmin]

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            # 获取字段从而知道操作哪个模型类与序列化类
            self.Report = model_dict[request.data['Report']]
            self.Serializer = serializer_dict[request.data['Report'] + 'Serializer']
            return self.get_reports(request)
        except Exception as e:
            return Response({'error': 'Invalid data:' + str(e)}, status=status.HTTP_400_BAD_REQUEST)

    def get_reports(self, request):
        # 获取id，根据id修改该条目,用序列化
        for author in request.data['authors']:
            author['name'] = self.get_name(author)
        serializer = self.Serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'success': 'Report create successfully'}, status=200)
        else:
            return Response({'error': 'Invalid data:' + str(serializer.errors)}, status=400)

    def get_name(self, author):
        # 去User模型根据request.data['authors'][0]['account']获取name
        return User.objects.get(username=author['account']).name


# 删除条目
class DeleteView(APIView):
    Report = None
    Serializer = None
    permission_classes = [IsTDAdmin]

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            # 获取字段从而知道操作哪个模型类与序列化类
            self.Report = model_dict[request.data['Report']]
            self.Serializer = serializer_dict[request.data['Report'] + 'Serializer']
            report = self.Report.objects.get(id=request.data['id'])
            if report.revstatus == '审核通过':
                return Response({'error': '当前信息已经通过审核，若要删除请取消审核通过'}, status=403)
            else:
                return self.get_reports(report)
        except Exception as e:
            return Response({'error': 'Invalid data: ' + str(e)}, status=400)

    def get_reports(self, report):
        # 获取id，根据id删除该条目
        report.delete()
        return Response({'success': 'Report deleted successfully'}, status=200)


# 修改条目
class UpdateView(APIView):
    permission_classes = [IsTDAdmin]
    Report = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            self.Report = model_dict[request.data['Report']]
            self.Serializer = serializer_dict[request.data['Report'] + 'Serializer']
            # 获取id，根据id修改该条目,用序列化
            report = self.Report.objects.get(id=request.data['id'])
            return self.get_reports(request, report)
        except Exception as e:
            return Response({'error': 'Invalid data:' + str(e)}, status=400)

    def get_reports(self, request, report):
        for author in request.data['authors']:
            author['name'] = self.get_name(author)
        if report.revstatus == '审核通过':
            report.get_author_scores()
        serializer = self.Serializer(report, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'success': 'Report updated successfully'}, status=200)
        else:
            return Response({'error': 'Invalid data:' + str(serializer.errors)}, status=400)

    def get_name(self, author):
        # 去User模型根据request.data['authors'][0]['account']获取name
        return User.objects.get(username=author['account']).name


# 获取所有条目
class GetView(APIView):
    permission_classes = [IsTDAdminOrIsReviewer]
    Report = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        # try:
        try:
            self.Report = model_dict[request.data['Report']]
            self.Serializer = serializer_dict[request.data['Report'] + 'Serializer']
            return self.get_reports(request)
        except Exception as e:
            return Response({'error': 'Invalid data: ' + str(e)}, status=400)

    # except Exception as e:
    #     return Response({'error': 'Invalid data:' + str(e)}, status=400)

    def get_reports(self, request):
        # 根据id返回TrainingReport

        reports = self.filter_reports_by_time(request)
        # 按系部筛选
        reports = self.filter_reports_by_user_department(request, reports)
        # 按人筛选
        reports = self.filter_reports_by_related_people(request, reports)
        # 按是否审核筛选
        reports = self.filter_reports_by_revstatus(request, reports)

        total_datas = len(reports)

        if request.data['page']:
            # 创建分页器实例，每页显示10条记录
            paginator = Paginator(reports, 10)
            # 获取当前页面
            page_number = request.data['page']
            reports = paginator.get_page(page_number)

        serializer = self.Serializer(reports, many=True, context={'request': request})
        return Response({'total_datas': total_datas, 'datas': serializer.data}, status=200)

    def filter_reports_by_time(self, request):
        start_time = request.data.get('start_time')
        end_time = request.data.get('end_time')
        if not start_time or not end_time:
            return Response({"error": "请提供 start_time 和 end_time 参数"}, status=status.HTTP_400_BAD_REQUEST)
            # 将字符串时间转换为 Python datetime 对象
        start_time = parse_datetime(start_time)
        end_time = parse_datetime(end_time)

        # 应用时间范围过滤
        reports = self.Report.objects.filter(time__range=(start_time, end_time))

        return reports

    def filter_reports_by_user_department(self, request, reports):
        """
        根据当前登录用户的department返回相应的内容，
        具体是返回report中authors的各元素的account（这个是user.username）所代表的用户的department
        和当前用户department相同的元素
        authors是json字段示例
    示例：
    [
      {
        'account':'23432',
        'name':'xxx',
        'role':'主讲人',
      },
      {
        'account':'34',
        'name':'xxx2',
        'role':'打杂',
      },
      {
        'account':'3434',
        'name':'xxx3',
        'role':'打杂',
      }
    ]

        """
        department =  request.data.get('department')
        if not department:
            return reports
        # 获取请求中的报告数据，这里假设reports是一个从数据库查询到的包含所有报告的QuerySet
        # 使用列表推导式过滤出每个报告中authors字段里，其account对应的用户department与当前用户department相同的报告
        filtered_reports = []

        for report in reports:
            for author in report.authors:
                if author['account'] and User.objects.filter(username=author['account']):
                    if User.objects.get(username=author['account']).department == department:
                        filtered_reports.append(report)
                        break

        return filtered_reports

    # 按照相关人物筛选
    def filter_reports_by_related_people(self, request, reports):
        """
        根据当前登录用户的department返回相应的内容，
        具体是返回report中authors的各元素的account（这个是user.username）所代表的用户的department
        和当前用户department相同的元素
        authors是json字段示例
    示例：
    [
      {
        'account':'23432',
        'name':'xxx',
        'role':'主讲人',
      },
      {
        'account':'34',
        """
        username = request.data.get('username')
        # 获取请求中的报告数据，这里假设reports是一个从数据库查询到的包含所有报告的QuerySet
        # 使用列表推导式过滤出每个报告中authors字段里，其account对应的用户department与当前用户department相同的报告
        filtered_reports = []
        if username is None or username == '000' or username == '':
            return reports
        for report in reports:
            for author in report.authors:
                if author['account'] == username:
                    filtered_reports.append(report)
                    break

        return filtered_reports

    # 按照是否审核筛选
    def filter_reports_by_revstatus(self, request, reports):
        revstatus = request.data.get('revstatus')
        # 获取请求中的报告数据，这里假设reports是一个从数据库查询到的包含所有报告的QuerySet
        # 使用列表推导式过滤出每个报告中authors字段里，其account对应的用户department与当前用户department相同的报告
        filtered_reports = []
        if revstatus is None or revstatus == '':
            return reports
        for report in reports:
            if report.revstatus == revstatus:
                    filtered_reports.append(report)

        return filtered_reports



# 增：上传附件
class AddFileView(APIView):
    permission_classes = [IsTDAdmin]
    parser_classes = [MultiPartParser, FormParser]  # 添加支持multipart/form-data的解析器
    Report = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            self.Report = model_dict[request.data['Report']]
            self.Serializer = serializer_dict[request.data['Report'] + 'Serializer']
            report = self.Report.objects.get(id=request.data['id'])

            return self.get_reports(request, report)

        except Exception as e:
            return Response({'error': 'Invalid data:' + str(e)}, status=400)

    def get_reports(self, request, report):
        # 上传附件信息
        # 获取上传的文件对象
        try:
            uploaded_file = request.FILES.get('file')  # 尝试从请求中获取文件

            if uploaded_file:
                # 如果有文件被上传，将其保存到报告的attachment字段
                report.attachment = uploaded_file
                self.change_attachment(report)
                report.save()
                return Response({"message": "Add report file successfully."}, status=status.HTTP_200_OK)
            else:
                return Response({"message": "No file uploaded."}, status=status.HTTP_400_BAD_REQUEST)

        except Exception as e:
            return Response({"message": "Add report failed: " + str(e)}, status=status.HTTP_400_BAD_REQUEST)

    def change_attachment(self,report):
        # 使用自定义的上传路径函数
        filename = os.path.basename(report.attachment.name)
        directory = report.custom_upload_to()
        new_path = os.path.join(directory, filename)
        # 构造新的文件路径的目录部分
        full_new_attachment_dir = os.path.join(MEDIA_ROOT, directory)
        # 如果目录不存在，则创建它
        if not os.path.exists(full_new_attachment_dir):
            os.makedirs(full_new_attachment_dir)
        else:
            # 清空目录内文件
            for file in os.listdir(full_new_attachment_dir):
                file_path = os.path.join(full_new_attachment_dir, file)
                if os.path.isfile(file_path):
                    os.remove(file_path)

        report.attachment.name = new_path


# 审批
class ApprovalView(APIView):
    # 仅reviewer组的用户可以访问
    permission_classes = [IsTDAdmin]
    Report = None
    Serializer = None

    def post(self, request):
        try:
            self.Report = model_dict[request.data['Report']]
            self.Serializer = serializer_dict[request.data['Report'] + 'Serializer']
            report = self.Report.objects.get(id=request.data['id'])
            return self.get_reports(request, report)
        except Exception as e:
            return Response({'error': 'Invalid data:' + str(e)}, status=400)

    def get_reports(self, request, report):
        # 获取id，根据id修改该条目,不用序列化
        try:
            # 获取id，根据id修改该条目,不用序列化
            report.revstatus = request.data['revstatus']
            report.reviewer = request.user.name
            report.review_time = timezone.now()
            if request.data['revstatus'] == '审核通过':
                report.get_author_scores()
            else:
                report.cancel_user_score()
            report.save()
            return Response({"message": "审批成功"}, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({"message": "审批失败：" + str(e)}, status=status.HTTP_400_BAD_REQUEST)
